﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace Nirvana
{
    /// <summary>
    /// AssetBundleName检测规则脚本，用于设置那些目录需要打AB包
    /// 注意：
    ///     规则文件必须存放在资源的父目录或同一级目录下。便于不同资源模块的管理。
    /// </summary>
    [CreateAssetMenu(fileName = "@AssetBundleNameImportRule", menuName = "Nirvana/Asset/AssetBundleNameImportRule")]

    public class AssetBundleNameImportRule : ScriptableObject
    {
        /// <summary>
        /// 指定检测规则的资源
        /// </summary>
        [Tooltip("通过哪些资源.")]
        [SerializeField]
        private ListStringVariate includeRegexs;
        /// <summary>
        /// 忽略规则检测
        /// </summary>
        [Tooltip("排除哪些资源.")]
        [SerializeField]
        private ListStringVariate excludeRegexs;

        [Tooltip("排除指定的后缀文件.")]
        [SerializeField]
        private ListStringVariate ingoreExtension;

        [Tooltip("Bundle Name 命名格式.")]
        [SerializeField]
        private StringVariate assetBundleNameFormat;

        [Tooltip("清除当前目录下所有AssetBundleName.")]
        [SerializeField]
        private bool clearBundleName;

        string rootDirpath = "Assets/Resources";//默认只有Resources目录下才能打AB包
        /// <summary>
        /// 返回当前配置脚本的存放目录
        /// </summary>
        /// <returns></returns>
        public string GetDirectorName()
        {
            string assetpath = AssetDatabase.GetAssetPath(this);
            return Path.GetDirectoryName(assetpath);
        }

        public static AssetBundleNameImportRule[] GetAllAssetImportRule()
        {
            string[] allRules = AssetDatabase.FindAssets("t:AssetBundleNameImportRule");
            List<AssetBundleNameImportRule> tmps = new List<AssetBundleNameImportRule>(allRules.Length);
            foreach (var p in allRules)
            {
                string guid = AssetDatabase.GUIDToAssetPath(p);
                tmps.Add(AssetDatabase.LoadAssetAtPath<AssetBundleNameImportRule>(guid));
            }
            return tmps.ToArray();
        }

        public bool IsMatchRegex(string assetPath)
        {
            if (!includeRegexs.IsHasValue()) return false;

            string ruleDirname = GetDirectorName();
            ruleDirname = ruleDirname.Replace('/', '\\');
            if (ruleDirname[ruleDirname.Length - 1] != Path.DirectorySeparatorChar) ruleDirname += Path.DirectorySeparatorChar;

            string filename = assetPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
            //同一父目录下才检测规则
            if (!filename.StartsWith(ruleDirname, System.StringComparison.OrdinalIgnoreCase)) return false;

            //指定包含的规则
            var temparray = this.includeRegexs.GetValue().ToArray();
            Regex[] regexs = null;
            if (temparray != null && temparray.Length > 0)
            {
                regexs = new Regex[temparray.Length];
                for (int i = 0; i < temparray.Length; i++) regexs[i] = new Regex(temparray[i]);
            }

            //需要忽略的规则
            temparray = this.excludeRegexs.GetValue().ToArray();
            Regex[] exRegexs = null;
            if (temparray != null && temparray.Length > 0)
            {
                exRegexs = new Regex[temparray.Length];
                for (int i = 0; i < temparray.Length; i++) exRegexs[i] = new Regex(temparray[i]);
            }

            string input = DirectoryUtil.RelativePath(GetDirectorName(), assetPath);
            if (regexs != null)
            {
                bool flag = false;
                foreach (Regex r in regexs)
                {
                    if (r.IsMatch(input))
                    {
                        flag = true;
                    }
                }
                if (!flag)
                {
                    return false;
                }
            }
            if (exRegexs != null)
            {
                bool flag2 = false;
                foreach (Regex r in exRegexs)
                {
                    if (r.IsMatch(input))
                    {
                        flag2 = true;
                        break;
                    }
                }
                if (flag2)
                {
                    return false;
                }
            }
            return true;
        }

        public void MarkAssetBundle(string asset)
        {
            //脚本不设置
            if (asset.EndsWith(".cs") || asset.Contains("ImportRule")
                || asset.Contains("Readme") || asset.Contains("readme") || asset.Contains("说明")) //规则文件不需要
            {
                return;
            }

            AssetImporter importer = AssetImporter.GetAtPath(asset);
            if (importer == null)
            {
                return;
            }

            if (assetBundleNameFormat.IsHasValue())
            {
                SetAssetBundleName(importer);
            }

        }

        private void SetAssetBundleName(AssetImporter import)
        {


            string filePath = DirectoryUtil.RelativePath(rootDirpath, import.assetPath);
            filePath = filePath.Replace("\\", "/");
            if(ingoreExtension.IsHasValue() && ingoreExtension.GetValue().Count > 0)
            {
                var exts = ingoreExtension.GetValue();
                foreach (var s in exts)
                {
                    if (string.IsNullOrEmpty(s)) continue;
                    string ext = Path.GetExtension(filePath);
                    if (s.EndsWith(ext)) return;
                }
            }


            var bundleName = UnitySystemTool.ParseSpriteTag(this.assetBundleNameFormat.GetValue(), filePath).ToLower();
            bundleName = bundleName.ToLower().Replace("/", ".");
            if (!string.Equals(import.assetBundleName, bundleName))
            {
                import.assetBundleName = bundleName + ".assetbundle";
                //import.SaveAndReimport();
            }
            //AssetDatabase.Refresh();
        }


        /// <summary>
        /// 清除AB Name
        /// </summary>
        public void ClearCurDirAssetBundleName()
        {
            AssetDatabase.RemoveUnusedAssetBundleNames();
            if (clearBundleName)
            {
                rootDirpath = rootDirpath.Replace('\\', '/');
                var dirPath = GetDirectorName().Replace('\\', '/');
                string filePath = "";
                if (dirPath == rootDirpath) //在主目录下
                {
                    filePath = rootDirpath;
                }
                else
                {
                    filePath = DirectoryUtil.RelativePath(rootDirpath, dirPath);
                }
               
                filePath = filePath.Replace("\\", "/");
                var allAssets = AssetDatabase.GetAllAssetPaths();
                
                foreach (var s in allAssets)
                {
                    if (s.EndsWith(".cs"))
                    {
                        continue;
                    }
                    if (!s.Contains(filePath)) continue; //不是当前目录下的忽略

                    var import = AssetImporter.GetAtPath(s);
                    if (import != null && !string.IsNullOrEmpty(import.assetBundleName))
                    {
                        import.assetBundleName = string.Empty;
                    }

                }
                AssetDatabase.Refresh();
            }
        }

        public void ClearAllAssetBundleName()
        {
            AssetDatabase.RemoveUnusedAssetBundleNames();
            var allABNames = AssetDatabase.GetAllAssetBundleNames();
            foreach(var s in allABNames)
            {
                AssetDatabase.RemoveAssetBundleName(s, true);
            }
            AssetDatabase.Refresh();
        }
    }
}

